import { omit } from "lodash-es";
import type { Key } from "antd/lib/table/interface";
import type { BasicTableProps, TableRowSelection } from "../types/table";
import { ROW_KEY } from "../const";
import { findNodeAll } from "@/utils/helper/treeHelper";
import { isFunction } from "@/utils/is";
import { useEffect, useMemo, useRef, useState } from "react";
import { nextTick } from "@/utils";

export function useRowSelection(propsRef: BasicTableProps, tableData: Recordable[], selectionChange?: Fn) {
	const tableDataRef = useRef(tableData);

	const selectedRowKeysRef = useRef<Key[]>([]);
	const selectedRowRef = useRef<Recordable[]>([]);
	/**@updateBy:Jok-2024/12/23-15:33-to trigger useMemo change */
	const [selectedRowKeysState, setSelectedRowKeysState] = useState<Key[]>([]);

	const getRowSelectionRef = useMemo((): TableRowSelection | null => {
		const { rowSelection } = propsRef;
		if (!rowSelection) return null;

		return {
			selectedRowKeys: selectedRowKeysState,
			onChange: (selectedRowKeys: Key[]) => {
				setSelectedRowKeys(selectedRowKeys);
			},
			...omit(rowSelection, ["onChange"])
		};
	}, [propsRef.rowSelection, selectedRowKeysState]);

	useEffect(() => {
		tableDataRef.current = tableData;
		return () => {
			tableDataRef.current = [];
		};
	}, [tableData]);

	useEffect(() => {
		setSelectedRowKeys(propsRef.rowSelection?.selectedRowKeys);
	}, [propsRef.rowSelection?.selectedRowKeys]);

	useEffect(() => {
		nextTick(() => {
			const { rowSelection } = propsRef;
			if (rowSelection) {
				const { onChange } = rowSelection;
				if (onChange && isFunction(onChange)) onChange(getSelectRowKeys(), getSelectRows());
			}
			selectionChange &&
				selectionChange({
					keys: getSelectRowKeys(),
					rows: getSelectRows()
				});
		});
	}, [propsRef.rowSelection, selectedRowKeysState]);

	const getAutoCreateKey = useMemo(() => {
		return propsRef.autoCreateKey && !propsRef.rowKey;
	}, [propsRef.autoCreateKey, propsRef.rowKey]);

	const getRowKey = useMemo(() => {
		const { rowKey } = propsRef;
		return getAutoCreateKey ? ROW_KEY : rowKey;
	}, [propsRef.rowKey]);

	function setSelectedRowKeys(rowKeys?: Key[]) {
		selectedRowKeysRef.current = rowKeys || [];
		setSelectedRowKeysState(rowKeys || []);
		const allSelectedRows = findNodeAll(
			tableDataRef.current.concat(selectedRowRef.current),
			item => rowKeys?.includes(item[getRowKey as string]),
			{
				children: propsRef?.childrenColumnName ?? "children"
			}
		);
		const trueSelectedRows: any[] = [];
		rowKeys?.forEach((key: Key) => {
			const found = allSelectedRows.find(item => item[getRowKey as string] === key);
			found && trueSelectedRows.push(found);
		});
		selectedRowRef.current = trueSelectedRows;
	}

	function setSelectedRows(rows: Recordable[]) {
		selectedRowRef.current = rows;
	}

	function clearSelectedRowKeys() {
		selectedRowRef.current = [];
		selectedRowKeysRef.current = [];
		setSelectedRowKeysState([]);
	}

	function deleteSelectRowByKey(key: string) {
		const selectedRowKeys = selectedRowKeysRef.current;
		const index = selectedRowKeys.findIndex(item => item === key);
		if (index !== -1) selectedRowKeysRef.current.splice(index, 1);
	}

	function getSelectRowKeys() {
		return selectedRowKeysRef.current;
	}

	function getSelectRows() {
		return selectedRowRef.current as Recordable[];
	}

	function getRowSelection() {
		return getRowSelectionRef!;
	}

	return {
		getRowSelection,
		getRowSelectionRef,
		getSelectRows,
		getSelectRowKeys,
		setSelectedRowKeys,
		clearSelectedRowKeys,
		deleteSelectRowByKey,
		setSelectedRows
	};
}
